<?php
/**
 * 短信业务逻辑类
 * User: 苏近之
 * Date: 2019-03-23
 * Time: 18:15
 */

namespace app\user\service;

use app\common\base\SmsService as SmsBaseService;
use app\common\enum\SmsTemplateCode;
use app\user\enum\CacheKeys;
use app\user\exception\PhoneAgainRegister;
use app\user\exception\PhoneNotFound;
use app\user\exception\RegisterSmsSendFailed;
use think\facade\Cache;

class SmsService extends SmsBaseService
{

    // 注册短信发送时间间隔
    const SMS_REGISTER_INTERVAL_TIME_SECOND = 120;
    // 注册短信相同 IP 在一天内发送的次数
    const SMS_REGISTER_SEND_LIMIT_IP_FOR_DAY = 3;
    // 注册短信相同手机号在一天内发送的次数
    const SMS_REGISTER_SEND_LIMIT_PHONE_FOR_DAY = 3;
    // 注册短信过期时间
    const SMS_REGISTER_VERIFY_CODE_EXPIRE = 300;

    // 忘记密码短信发送时间间隔
    const SMS_FORGET_INTERVAL_TIME_SECOND = 120;
    // 忘记密码短信相同 IP 在一天内发送的次数
    const SMS_FORGET_SEND_LIMIT_IP_FOR_DAY = 3;
    // 忘记密码短信相同手机号在一天内发送的次数
    const SMS_FORGET_SEND_LIMIT_PHONE_FOR_DAY = 3;
    // 忘记密码短信过期时间
    const SMS_FORGET_VERIFY_CODE_EXPIRE = 300;

    /**
     * 手机号
     * @var string
     */
    protected static $phone;

    /**
     * 短信模板
     * @var string
     */
    protected static $templateCode;


    /**
     * 设置手机号
     * @param string $phone
     * @return SmsService
     */
    public static function setPhone($phone)
    {
        self::$phone = $phone;

        return new self;
    }

    /**
     * 发送注册短信验证码
     * @throws
     */
    public static function register()
    {
        // 设置短信模板
        static::$templateCode = SmsTemplateCode::REGISTER_TEMPLATE;
        // 检查限制
        static::before(
            self::SMS_REGISTER_SEND_LIMIT_IP_FOR_DAY,
            self::SMS_REGISTER_SEND_LIMIT_PHONE_FOR_DAY,
            function () {
                // 检查手机是否已经注册
                if(UserInfoService::hasRegisterWithPhone(static::$phone)){
                    throw new PhoneAgainRegister();
                }
            });
        // 发送手机验证码
        $result = static::send(self::SMS_REGISTER_VERIFY_CODE_EXPIRE);
        if (!$result) {
            throw new RegisterSmsSendFailed();
        }
        // 后续工作
        static::After(self::SMS_REGISTER_VERIFY_CODE_EXPIRE);
    }

    /**
     * 忘记密码
     * @throws RegisterSmsSendFailed
     * @throws \app\user\exception\SmsThanIpLimit
     * @throws \app\user\exception\SmsThanPhoneLimit
     * @throws \app\user\exception\SmsThanTimeIntervalLimit
     */
    public static function forget()
    {
        // 设置短信模板
        static::$templateCode = SmsTemplateCode::FORGET_PASSWORD_TEMPLATE;
        // 检查限制
        static::before(
            self::SMS_FORGET_SEND_LIMIT_IP_FOR_DAY,
            self::SMS_FORGET_SEND_LIMIT_PHONE_FOR_DAY,
            function () {
                // 检查手机是否已经注册
                if(!UserInfoService::hasRegisterWithPhone(static::$phone)){
                    throw new PhoneNotFound();
                }
            });
        // 发送手机验证码
        $result = static::send(self::SMS_FORGET_VERIFY_CODE_EXPIRE);
        if (!$result) {
            throw new RegisterSmsSendFailed();
        }
        // 后续工作
        static::After(self::SMS_FORGET_VERIFY_CODE_EXPIRE);
    }


    /**
     * 检查验证码是否正确
     * @param string|int $verifyCode 验证码
     * @return bool
     */
    public static function checkVerifyCode($verifyCode): bool
    {
        $key = sprintf(CacheKeys::SMS_SEND, self::$phone);
        $storeVerifyCode = Cache::get($key, 0);

        return ($storeVerifyCode == $verifyCode);
    }

    /**
     * 删除验证码缓存
     */
    public static function removeVerifyCode(): void
    {
        $key = sprintf(CacheKeys::SMS_SEND, self::$phone);
        Cache::rm($key);
    }

}